package cn.yeyiu.videoplayer;

import android.content.Context;
import android.graphics.Color;
import android.media.AudioManager;
import android.media.MediaPlayer;
import android.net.Uri;
import android.util.AttributeSet;
import android.util.Log;
import android.view.Gravity;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.widget.FrameLayout;
import android.widget.TextView;

import androidx.annotation.NonNull;

import java.io.IOException;
import java.util.Map;

import cn.yeyiu.util.AndroidUtil;


public class YeyiuVideoPlayer extends FrameLayout {
    private final String TAG = "YeyiuVideoPlayer";

    // 缩放模式
    public static final int SCALE_RATIO = 0;
    public static final int SCALE_FULL = 1;
    public static final int SCALE_RATIO_FULL = 2;
    public static final int SCALE_RAW = 3;

    // 播放状态 all possible internal states
    private static final int STATE_ERROR = -1;
    private static final int STATE_IDLE = 0;
    private static final int STATE_PREPARING = 1;
    private static final int STATE_PREPARED = 2;
    private static final int STATE_PLAYING = 3;
    private static final int STATE_PAUSED = 4;
    private static final int STATE_PLAYBACK_COMPLETED = 5;

    // 当前状态
    private int mCurrentState = STATE_IDLE;

    private Context mContext;
    private MediaPlayer mMediaPlayer;
    private SurfaceView mVideoView;
    private View quickTipView;
    private View netLoadingView;
    private TextView videoQuick;
    private TextView loadingText;

    AudioManager am;

    // 视频文件地址
    private Uri mUri;
    // 视频请求header
    private Map<String, String> mHeader;

    private LayoutParams surfaceViewParams;

    // 加载完成事件
    private MyPlayerListener myPlayerListener;


    // init
    public YeyiuVideoPlayer(Context context) {
        this(context, null);
    }

    public YeyiuVideoPlayer(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public YeyiuVideoPlayer(Context context, AttributeSet attrs, int defStyleAttr) {
        this(context, attrs, defStyleAttr, 0);
    }

    public YeyiuVideoPlayer(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
        initVideoView(context);
    }

    // 初始化
    private void initVideoView(Context context) {
        this.mContext = context;
        this.setBackgroundColor(Color.BLACK);

        this.initRenderView();
        am = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
    }

    // 初始化界面 视频，字幕等
    private void initRenderView() {
        mVideoView = new SurfaceView(mContext);
        mVideoView.getHolder().addCallback(new SurfaceHolder.Callback() {
            @Override
            public void surfaceCreated(@NonNull SurfaceHolder holder) {
                mMediaPlayer.setDisplay(holder);
                mMediaPlayer.setScreenOnWhilePlaying(true);
            }

            @Override
            public void surfaceChanged(@NonNull SurfaceHolder holder, int format, int width, int height) {
            }

            @Override
            public void surfaceDestroyed(@NonNull SurfaceHolder holder) {
                mMediaPlayer.setDisplay(null);
            }
        });

        surfaceViewParams = new LayoutParams(0, 0, Gravity.CENTER);
        this.addView(mVideoView, 0, surfaceViewParams);

        mCurrentState = STATE_IDLE;

        quickTipView = LayoutInflater.from(mContext).inflate(R.layout.item_video_seek_tips, this, false);
        videoQuick = quickTipView.findViewById(R.id.video_quick);
        this.addView(quickTipView);

        netLoadingView = LayoutInflater.from(mContext).inflate(R.layout.item_video_net_loading, this, false);
        loadingText = netLoadingView.findViewById(R.id.video_loading);
        this.addView(netLoadingView);

    }

    public void setTip(String tip) {
        videoQuick.setText(tip);
    }

    public void showTip() {
        quickTipView.setVisibility(VISIBLE);
    }

    public void hideTip() {
        quickTipView.setVisibility(INVISIBLE);
    }

    public boolean isTipShowing() {
        return quickTipView.getVisibility() == View.VISIBLE;
    }

    // 设置监听
    private void setListener() {

        mMediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
            @Override
            public void onPrepared(MediaPlayer mp) {
                mCurrentState = STATE_PREPARED;
                myPlayerListener.onPrepared();
            }
        });
        mMediaPlayer.setOnErrorListener(new MediaPlayer.OnErrorListener() {
            @Override
            public boolean onError(MediaPlayer mp, int what, int extra) {
                mCurrentState = STATE_ERROR;
                myPlayerListener.onError(what, extra);
                return true;
            }
        });
        mMediaPlayer.setOnInfoListener(new MediaPlayer.OnInfoListener() {
            @Override
            public boolean onInfo(MediaPlayer mp, int what, int extra) {
                switch (what) {
                    case 1:

                        break;
                    case MediaPlayer.MEDIA_INFO_BUFFERING_START:
                        loadingText.setText("加载中，请稍后");
                        netLoadingView.setVisibility(VISIBLE);
                        break;
                    case MediaPlayer.MEDIA_INFO_BUFFERING_END:
                        netLoadingView.setVisibility(INVISIBLE);
                        break;
                    case MediaPlayer.MEDIA_INFO_VIDEO_TRACK_LAGGING:
                        loadingText.setText("加载较慢，请稍后");
                        netLoadingView.setVisibility(VISIBLE);
                        break;
                    default:
                        break;
                }
                return true;
            }
        });
    }

    //-------------------------------------
    //         2333333333333333
    //-------------------------------------


    private MediaPlayer createPlayer() {
        MediaPlayer ijkMediaPlayer = null;
        if (mUri != null) {
            ijkMediaPlayer = new MediaPlayer();

            ijkMediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
        }
        return ijkMediaPlayer;
    }

    // 准备播放
    private void openVideo() {
        if (mUri == null) {
            return;
        }
        release();

        am.requestAudioFocus(null, AudioManager.STREAM_MUSIC, AudioManager.AUDIOFOCUS_GAIN);

        try {
            mMediaPlayer = createPlayer();

            this.setListener();

            mMediaPlayer.setDataSource(mContext, mUri, mHeader);
            mMediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
            mMediaPlayer.setScreenOnWhilePlaying(true);

            mMediaPlayer.prepareAsync();

            mCurrentState = STATE_PREPARING;
        } catch (IOException | IllegalArgumentException ex) {
            Log.w(TAG, "Unable to open content: " + mUri, ex);
            myPlayerListener.onError(0, -1);
        }
    }


    // 在可播放状态
    private boolean isInPlaybackState() {
        return (mMediaPlayer != null &&
                mCurrentState != STATE_ERROR &&
                mCurrentState != STATE_IDLE &&
                mCurrentState != STATE_PREPARING);
    }

    //-------------------------------------
    //         video控制
    //-------------------------------------

    // 设置资源路径
    public void setVideoPath(String path) {
        setVideoURI(Uri.parse(path));
    }

    public void setVideoPath(String path, Map<String, String> header) {
        setVideoURI(Uri.parse(path), header);
    }

    public void setVideoURI(Uri uri) {
        setVideoURI(uri, null);
    }

    public void setVideoURI(Uri uri, Map<String, String> headers) {
        mUri = uri;
        mHeader = headers;
        openVideo();
        requestLayout();
        invalidate();
    }

    public void releaseWithoutStop() {
        if (mMediaPlayer != null)
            mMediaPlayer.setDisplay(null);
    }

    public void release() {
        if (mMediaPlayer != null) {
            if (isInPlaybackState()) {
                mMediaPlayer.stop();
            }
            mMediaPlayer.reset();
            mMediaPlayer.release();
            mMediaPlayer = null;
            mCurrentState = STATE_IDLE;
            am.abandonAudioFocus(null);
        }
    }

    public boolean isPlaying() {
        return isInPlaybackState() && mMediaPlayer.isPlaying();
    }

    public void start() {
        if (isInPlaybackState()) {
            mMediaPlayer.start();
            mCurrentState = STATE_PLAYING;
        }
    }

    public void pause() {
        if (isInPlaybackState()) {
            if (mMediaPlayer.isPlaying()) {
                mMediaPlayer.pause();
                mCurrentState = STATE_PAUSED;
            }
        }
    }

    public void suspend() {
        release();
    }

    public void resume() {
        if (mMediaPlayer == null) {
            openVideo();
        } else {
            start();
        }
    }

    public void stopPlayback() {
        if (mMediaPlayer != null) {
            mMediaPlayer.release();
            mMediaPlayer = null;
            mCurrentState = STATE_IDLE;
            am.abandonAudioFocus(null);
        }
    }

    public int getDuration() {
        if (isInPlaybackState()) {
            return mMediaPlayer.getDuration();
        }
        return -1;
    }

    public int getCurrentPosition() {
        if (isInPlaybackState()) {
            return mMediaPlayer.getCurrentPosition();
        }
        return 0;
    }

    public void seekTo(int msec) {
        if (isInPlaybackState()) {
            mMediaPlayer.seekTo(msec);
        }
    }

    // 改变显示模式
    public void changeSize(int type) {
        int windowWidth = getWidth();
        int windowHeight = getHeight();

        int videoWidth = mMediaPlayer.getVideoWidth();
        int videoHeight = mMediaPlayer.getVideoHeight();

        if (type == SCALE_RATIO) {// 按比例缩放
            // 判断窗口扁度 越大越扁
            float windowH = windowWidth / (float) windowHeight;
            // 判断视频扁度
            float videoH = videoWidth / (float) videoHeight;
            if (videoH > windowH) {// 视频扁，对齐宽度
                setSize(LayoutParams.MATCH_PARENT, (int) (windowWidth / videoH));
            } else { // 窗口扁，对齐高度
                setSize((int) (windowHeight * videoH), LayoutParams.MATCH_PARENT);
            }

        } else if (type == SCALE_FULL) { // 拉伸
            setSize(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);

        } else if (type == SCALE_RATIO_FULL) { // 铺满
            // 判断窗口扁度 越大越扁
            float windowH = windowWidth / (float) windowHeight;
            // 判断视频扁度
            float videoH = videoWidth / (float) videoHeight;
            if (videoH > windowH) {// 视频扁，对齐高度
                setSize((int) (videoH * windowHeight), LayoutParams.MATCH_PARENT);
            } else { // 窗口扁，对齐宽度
                setSize(LayoutParams.MATCH_PARENT, (int) (windowWidth / videoH));
            }

        } else if (type == SCALE_RAW) { // 原视频大小
            setSize(videoWidth, videoHeight);

        } else {
            AndroidUtil.toast("错误比例");
        }
    }

    // 视频大小
    public void setSize(int width, int height) {
        surfaceViewParams.width = width;
        surfaceViewParams.height = height;
        mVideoView.setLayoutParams(surfaceViewParams);
    }

    // 获取视频比例
    public boolean isVideoHorizontal() {
        return mMediaPlayer.getVideoWidth() > mMediaPlayer.getVideoHeight();
    }


    public void setSpeed(float speed) {
        if (mMediaPlayer.isPlaying()) {
            mMediaPlayer.setPlaybackParams(mMediaPlayer.getPlaybackParams().setSpeed(speed));
        } else {
            mMediaPlayer.setPlaybackParams(mMediaPlayer.getPlaybackParams().setSpeed(speed));
            mMediaPlayer.pause();
        }
    }

    // -------------------------------------------------
    // 23333333333333333333333
    // -------------------------------------------------

    public void setMyPlayerListener(MyPlayerListener myPlayerListener) {
        this.myPlayerListener = myPlayerListener;
    }

    // interface
    interface MyPlayerListener {
        void onPrepared();

        void onError(int what, int extra);
    }


    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        boolean isKeyCodeSupported = keyCode != KeyEvent.KEYCODE_BACK &&
                keyCode != KeyEvent.KEYCODE_VOLUME_UP &&
                keyCode != KeyEvent.KEYCODE_VOLUME_DOWN &&
                keyCode != KeyEvent.KEYCODE_VOLUME_MUTE &&
                keyCode != KeyEvent.KEYCODE_MENU &&
                keyCode != KeyEvent.KEYCODE_CALL &&
                keyCode != KeyEvent.KEYCODE_ENDCALL;
        if (isInPlaybackState() && isKeyCodeSupported) {
            if (keyCode == KeyEvent.KEYCODE_HEADSETHOOK ||
                    keyCode == KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE ||
                    keyCode == KeyEvent.KEYCODE_SPACE) {
                if (mMediaPlayer.isPlaying()) {
                    pause();
                } else {
                    start();
                }
                return true;
            } else if (keyCode == KeyEvent.KEYCODE_MEDIA_PLAY) {
                if (!mMediaPlayer.isPlaying()) {
                    start();
                }
                return true;
            } else if (keyCode == KeyEvent.KEYCODE_MEDIA_STOP
                    || keyCode == KeyEvent.KEYCODE_MEDIA_PAUSE) {
                if (mMediaPlayer.isPlaying()) {
                    pause();
                }
                return true;
            } else if (keyCode == KeyEvent.KEYCODE_DPAD_RIGHT) {
                seekTo(getCurrentPosition() + 10000);

            } else if (keyCode == KeyEvent.KEYCODE_DPAD_LEFT) {
                seekTo(getCurrentPosition() - 10000);

            } else if (keyCode == KeyEvent.KEYCODE_DPAD_UP) {
                am.adjustStreamVolume(AudioManager.STREAM_MUSIC,
                        AudioManager.ADJUST_RAISE,
                        AudioManager.FLAG_PLAY_SOUND | AudioManager.FLAG_SHOW_UI);
            } else if (keyCode == KeyEvent.KEYCODE_DPAD_DOWN) {
                am.adjustStreamVolume(AudioManager.STREAM_MUSIC,
                        AudioManager.ADJUST_LOWER,
                        AudioManager.FLAG_PLAY_SOUND | AudioManager.FLAG_SHOW_UI);
            }
        }

        return super.onKeyDown(keyCode, event);
    }


    @Override
    public boolean performClick() {
        return super.performClick();
    }
}
